package com.njy.sentinel.controller;


import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.Rule;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.njy.sentinel.blockexception.Block;
import org.apache.tomcat.util.modeler.ParameterInfo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;


@RestController
public class sentinelLimitController {

    /**
     * 不能单独使用，必须与 blockHandler 属性配合使用；
     * 该属性指定的类中的 blockHandler 函数必须为 static 函数，否则无法解析。
     * @return
     */
    @GetMapping("/testA")
    @SentinelResource(blockHandler = "test",blockHandlerClass = {Block.class},value = "/testA")
    public String testA(){
        initRules("/testA");
        return "testA";
    }

    @GetMapping("/testB")
    public String testB(){
        return "testB";
    }

    /**
     * 通过SPHU方式定义资源
     * @return
     */
    @GetMapping("/testC")
    public String testC(){
        Entry entry = null;
        try {
            entry = SphU.entry("SPHUtestC");
            return "testC";
        } catch (BlockException e) {
            e.printStackTrace();
            return "testC 服务被限流";
        }finally {
            entry.exit();
        }

    }

    /**
     * 通过SPHO方式定义资源
     * @return
     */
    @GetMapping("/testD")
    public String testD(){
        if(SphO.entry("SPHOtestD")){
            // 务必保证finally会被执行
            try {

                return "testD" ;
            } finally {
                SphO.exit();
            }
        }else {
            return "testD 服务被限流";
        }
    }

    /**
     * 通过注解方式定义资源
     */
    @SentinelResource(value = "SentinelResourceTestE",blockHandler  = "handlerMethod")
    @GetMapping("/teste")
    public String teste(){
        initRules("SentinelResourceTestE");
        return "teste";
    }

    public String handlerMethod(BlockException blockException){
        return "teste服务访问失败! 您已被限流，请稍后重试--->同一类中";
    }

    public static  void  initRules(String name){
        List<FlowRule> rules = new ArrayList<>();
        //定义一个限流规则对象
        FlowRule rule = new FlowRule();
        //资源名称
        rule.setResource(name);
        //限流阈值的类型
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置 QPS 的阈值为 1
        rule.setCount(1);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }

}
